/*
 * Copyright 2004-2006 asoft
 * 本软件及其所有拷贝的名称，与光盘上或本软件中注明的公司同在。
 * 本软件及文档享有版权，并受国家版权法及国际协约条款的保护。
 * 您不可以从本软件中去掉其版权声明；并保证为本软件的拷贝（本部或部分）复制版权声明。
 * 您同意制止以任何形式非法拷贝本软件及文档。
 * 版权信息参见：
 *      http://www.asoft.cn/licenses
 */

package com.asoft.common.sysframe.valid;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;

import com.asoft.common.sysframe.define.SysFrameParams;
import com.asoft.common.sysframe.define.UserStatus;
import com.asoft.common.sysframe.manager.UserManager;
import com.asoft.common.sysframe.model.User;
import com.asoft.common.util.mvc.valid.UserValidator;
import com.asoft.common.util.mvc.valid.ValidatedResult;

/**
 * <p>Title: 登录</p>
 * <p>Description: 登录 Org </p>
 * <p>Copyright: Copyright (c) 2004-2006</p>
 * <p>Company: asoft</p>
 * @ $Author: amon.lei $
 * @ $Date: 2007-2-20 $
 * @ $Revision: 1.0 $
 * @ created in 2007-2-20
 *
 */

public class LogginValidator extends UserValidator
{
        static Logger logger = Logger.getLogger(LogginValidator.class);
        
        public static final Map errorCount4Wait = new HashMap();
        
        public static final Map errorCount = new HashMap();
        
        public static final Map lastLoginTime = new HashMap();

        /**
         * 登陆的校验
         *
         * @ param: HttpServletRequest request
         * @ param: ValidatedResult vr 校验结果存放器
         * @ param: String[] params 配置参数
         */

        public void validing(HttpServletRequest request,ValidatedResult vr,String[] params)
        {
                logger.debug("开始登录前校验");
                this.monitor();
                UserManager userManager = (UserManager)this.getBean("userManager");
                User user = userManager.getByAccount(request.getParameter("account"));
                if(user == null)
                {
                        vr.setErrMess("errMess","帐户不存在");
                        return;
                }
                if(user.getStatus()!= UserStatus.VALID)
                {
                        vr.setErrMess("errMess","帐号处于" + user.getStatusName() + "状态,无法登录");
                        return;
                }
                // 是否超过错误次数
                if(!this.isAllowed2Login(user))
                {
                        logger.debug("密码错误次数过多");
                        vr.setErrMess("errMess","密码错误次数过多,系统暂停该帐号的访问,请在5分钟后重试");
                        return;
                }
                this.monitor();
                // 密码 校验
                if(!user.checkPW(request.getParameter("password")))
                {
                        this.pwErrCount4WaitPP(user.getAccount());
                        if(this.has2BeLocked(user))
                        {
                                logger.info("密码错误次数过多,系统锁定该帐号(" + user.getAccount() + ")");
                                vr.setErrMess("errMess","密码错误次数过多,系统锁定该帐号");
                                user.setStatus(UserStatus.LOCKED);
                                userManager.update(user);
                                this.resetPwErrCount(user.getAccount());
                                this.resetPwErrCount4Wait(user.getAccount());
                                return;
                        }
                        vr.setErrMess("errMess","密码不正确");
                        return;
                }
                else
                {
                        Date now = new Date();
                        if(!user.getPwLimtDate().after(now))
                        {
                                vr.setErrMess("errMess","密码已经过期");
                                return;
                        }
                        if(!user.getIdLimtDate().after(now))
                        {
                                vr.setErrMess("errMess","帐号已经过期");
                                return;
                        }
                        this.resetPwErrCount(user.getAccount());
                        this.resetPwErrCount4Wait(user.getAccount());
                        logger.debug("允许登录");
//                        user.getOrgs();
//                        user.getPosts();
//                        user.getColumns();
                        request.getSession().setAttribute(SysFrameParams.CURRENT_USER_ID,user.getId());
                }
        }
        
        // 是否小于密码错误次数（等待）
        public boolean lessThanPwErrCount4Wait(User user)
        {
                if(user.getPwErrorNum() == 0)
                {
                        this.resetPwErrCount4Wait(user.getAccount());
                        return true;
                }
                else
                {
                        return this.getPwErrCount4Wait(user.getAccount()) < user.getPwErrorNum();
                }
        }
        
        // 是否小于密码错误次数（等待）
        public boolean has2BeLocked(User user)
        {
                if(user.getPwErrorLock() == 0)
                {
                        this.resetPwErrCount(user.getAccount());
                        return false;
                }
                else
                {
                        return !(this.getPwErrCount(user.getAccount()) < user.getPwErrorLock());
                }
        }
        
        // 取得密码错误次数4等待
        public int getPwErrCount4Wait(String account)
        {
                Integer i = (Integer)errorCount4Wait.get(account);
                if(i == null)
                {
                        return 0;
                }
                else
                {
                        return i;
                }
        }
        
        // 取得密码错误次数4等待
        public int pwErrCount4WaitPP(String account)
        {
                this.setLoginTime(account);
                int i = this.getPwErrCount4Wait(account);
                i ++;
                synchronized(errorCount4Wait)
                {
                        errorCount4Wait.put(account,i);
                }
                int j = this.getPwErrCount(account);
                j++;
                synchronized(errorCount)
                {
                        errorCount.put(account,j);
                }
                return i;
        }
        
        // 取得密码错误次数
        public int getPwErrCount(String account)
        {
                Integer i = (Integer)errorCount.get(account);
                if(i == null)
                {
                        return 0;
                }
                else
                {
                        return i;
                }
        }
        
        // 重置密码错误次数4等待
        public void resetPwErrCount4Wait(String account)
        {
                logger.debug("重置密码错误次数4等待");
                synchronized(errorCount4Wait)
                {
                        errorCount4Wait.remove(account);
                }
                synchronized(lastLoginTime)
                {
                        lastLoginTime.remove(account);
                }
        }
        
        // 重置密码错误次数
        public void resetPwErrCount(String account)
        {
                logger.debug("重置密码错误次数");
                synchronized(errorCount)
                {
                        errorCount.remove(account);
                }
                
        }

        // 设置登录时间
        public void setLoginTime(String account)
        {
                synchronized(lastLoginTime)
                {
                        lastLoginTime.put(account,new Date());
                }
        }
        
        public Date getLoginTime(String account)
        {
                return (Date)lastLoginTime.get(account);
        }
        
        public boolean isAllowed2Login(User user)
        {
                if(this.lessThanPwErrCount4Wait(user))
                {
                        return true;
                }
                else
                {
                        Date llt = this.getLoginTime(user.getAccount());
                        if(llt != null)
                        {
                                Date now = new Date();
                                now.setMinutes(now.getMinutes() - 5); // 五分钟后允许访问
//                                now.setSeconds(now.getSeconds() - 20);
                                if(!now.before(llt))
                                {
                                        logger.debug("密码错误次数置0"); 
                                        this.resetPwErrCount4Wait(user.getAccount());
                                        return true;
                                }
                                else
                                {
                                        return false;
                                }
                        }
                        else
                        {
                                return true;
                        }
                }
        }
        
        public void monitor()
        {
                if(logger.isDebugEnabled())
                {
                        logger.debug("＝＝＝＝errorCount＝＝＝＝");
                        this.out(errorCount);
                        logger.debug("＝＝＝＝errorCount4Wait＝＝＝＝");
                        this.out(errorCount4Wait);
                        logger.debug("＝＝＝＝lastLoginTime＝＝＝＝");
                        this.out(lastLoginTime);
                }
        }
        
        private void out(Map map)
        {
                Object[] keys = map.keySet().toArray();
                for(int i = 0; i < keys.length; i ++)
                {
                        System.out.println(keys[i] + " : " + map.get(keys[i]));
                }
        }

}
